package model.cell.tower;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import model.bullet.AbstractBullet;
import model.cell.AbstractCell;
import model.enemy.AbstractEnemy;
import model.game.EnemyWave;



public abstract class AbstractTower extends AbstractCell implements ImageObserver {
	
	protected TowerThread _towerThread = new TowerThread();
	
	protected Image _img = null;
	
	protected EnemyWave _enemyWave;
	
	protected List<AbstractBullet> _bullets = Collections.synchronizedList(new ArrayList<AbstractBullet>());
	
	protected int _range = 100;
	
	protected boolean _drawArea = false;
	
	protected int _fireInterval = 500;
	
	
	public AbstractTower(Point pos, Dimension dim, EnemyWave enemyWave) {
		
		super(pos, dim);
		
		_enemyWave = enemyWave;
		
		// TODO  fixme
		if (null != _enemyWave)
			_towerThread.start();
	}


	public boolean imageUpdate(Image arg0, int arg1, int arg2, int arg3, int arg4, int arg5) {
		
		return false;
	}
	
	
	public void draw(Graphics g) {
		
		_drawTower(g);
		_drawArea(g);
	}


	protected void _drawTower(Graphics g) {
		
		if (null != _img)
			g.drawImage(_img, _rect.x, _rect.y, _rect.width, _rect.height, this);
	}


	private void _drawArea(Graphics g) {
		
		if (_drawArea) {
			g.setColor(Color.GREEN);
			g.drawOval(_rect.x + (_rect.width / 2) - _range, _rect.y + (_rect.height / 2) - _range, _range*2, _range*2);
		}
	}

	
	public void drawBullets(Graphics g) {
		
		synchronized(_bullets) {
			for (Iterator<AbstractBullet> it = _bullets.iterator(); it.hasNext();) {
				AbstractBullet bullet = (AbstractBullet) it.next();
				bullet.draw(g);
			}
		}
	}
	
	
	public void drawArea() {
		
		_drawArea = !_drawArea;
	}
	
	
	public synchronized void bulletIsDead(AbstractBullet bullet) {
		
		_bullets.remove(bullet);
	}
	
	
	protected abstract AbstractBullet _createBullet(AbstractEnemy enemy);
	
	
	public AbstractEnemy findEnemy() {
		
		ArrayList<AbstractEnemy> enemies = _enemyWave.getEnemies();
		
		for (Iterator<AbstractEnemy> it = enemies.iterator(); it.hasNext();) {
			
			AbstractEnemy enemy = (AbstractEnemy) it.next();
			double distance = _getEnemyDistance(enemy);
			
			if ( distance < _range ) {
				return enemy;
			}
		}
		
		return null;
	}
	
	
	public boolean enemyInRange(AbstractEnemy enemy) {
		
		double distance = _getEnemyDistance(enemy);
		
		if ( distance < _range ) {
			return true;
		}
		
		return false;
	}
	
	
	private double _getEnemyDistance(AbstractEnemy enemy) {
		
		Point enemyPos = enemy.getPosition();
		int distanceX = Math.abs(enemyPos.x - (_rect.x + _rect.width / 2 ));
		int distanceY = Math.abs(enemyPos.y - (_rect.y + _rect.height / 2 ));
		
		return Math.sqrt(distanceX*distanceX + distanceY*distanceY);
		
	}
	
	
	public void setEnemyWave(EnemyWave enemyWave) {
		
		this._enemyWave = enemyWave;
	}
	
	
	public void start() {
		
		_towerThread.start();
	}
	
	
	class TowerThread extends Thread {
		
		public void run() {
			
			while(true) {
				
				AbstractEnemy enemy = findEnemy();
				if ( null != enemy ) {
					
					AbstractBullet bullet = _createBullet(enemy);
					if (null != bullet) {
						_bullets.add(bullet);						
					}
				}
				
				try {
					sleep( _fireInterval );
				} catch ( Exception e ) {} 
			}
		}
	}
	
}
